package cc.autoapi.pucong.liteflow.design.core.configuration;

import cc.autoapi.pucong.liteflow.design.core.exception.DesignException;
import cc.autoapi.pucong.liteflow.design.mobal.DesignUser;
import cc.autoapi.pucong.liteflow.design.mobal.HeaderDesignUser;
import cc.autoapi.pucong.liteflow.design.mobal.JsonBean;
import cc.autoapi.pucong.liteflow.design.mobal.Valid;
import cc.autoapi.pucong.liteflow.design.utils.AESEncryptUtil;
import cc.autoapi.pucong.liteflow.design.utils.Constants;
import cc.autoapi.pucong.liteflow.design.utils.MD5Utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Objects;

/**
 * 默认UI鉴权实现
 *
 * @author pucong
 */
public class DefaultAuthorizationInterceptor implements AuthorizationInterceptor {
    private static final Logger log = LoggerFactory.getLogger(DefaultAuthorizationInterceptor.class);

    private Boolean requireLogin;
    private Boolean readonly;
    private Boolean enable;
    private String validToken;
    private DesignUser designUser;

    public DefaultAuthorizationInterceptor(Boolean requireLogin, Boolean readonly, Boolean enable, String username, String password) {
        this.requireLogin = requireLogin;
        this.readonly = readonly;
        this.enable = enable;
        if (requireLogin) {
            this.validToken = MD5Utils.encrypt(String.format("%s||%s", username, password));
            this.designUser = new DesignUser(username, username, this.validToken);
        }
    }

    @Override
    public boolean requireLogin() {
        return this.requireLogin;
    }

    @Override
    public boolean readonly() {
        return this.readonly;
    }

    @Override
    public boolean isenable() {
        return this.enable;
    }

    @Override
    public HeaderDesignUser getUserByHeader(HttpServletRequest request) throws DesignException {
        String token = request.getHeader(Constants.DESIGN_TOKEN_HEADER);
        if (StringUtils.isBlank(token)) {
            return null;
        }
        String userJson = AESEncryptUtil.decrypt(token);
        ObjectMapper objectMapper = new ObjectMapper();
        HeaderDesignUser loginUser = null;
        try {
            loginUser = objectMapper.readValue(userJson, HeaderDesignUser.class);
        } catch (JsonProcessingException e) {
            throw new DesignException("获取登录用户对象异常");
        }
        return loginUser;
    }

    @Override
    public DesignUser loginCheck(String username, String password) throws DesignException {
        if (requireLogin() && Objects.equals(MD5Utils.encrypt(String.format("%s||%s", username, password)), this.validToken)) {
            return designUser;
        }
        throw new DesignException("用户名或密码不正确");
    }

    @Override
    public void logout(HttpServletRequest request) {
        // 清理头部的token
        request.removeAttribute(Constants.DESIGN_TOKEN_HEADER);
    }

    @Override
    public boolean checkLogin(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) {
        Valid valid = handlerMethod.getMethodAnnotation(Valid.class);
        boolean requiredLogin = requireLogin();
        boolean validRequiredLogin = (valid != null);
        HeaderDesignUser headerDesignUser = getUserByHeader(request);
        if (headerDesignUser != null) {
            request.setAttribute(Constants.ATTRIBUTE_DESIGN_USER, headerDesignUser);
        }
        if (readonly() && validRequiredLogin) {
            returnJson(response, "readonly mode,can not fix data");
            return false;
        }
        if (requiredLogin && headerDesignUser == null && validRequiredLogin) {
            returnJson(response, "no power");
            return false;
        }
        if (!requiredLogin) {
            return true;
        }
        if (requiredLogin && validRequiredLogin) {
            if (headerDesignUser.getExpireTime().before(new Date())) {
                returnJson(response, "no power");
                return false;
            }
        }
        return true;
    }

    private void returnJson(HttpServletResponse response, String message) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try {
            writer = response.getWriter();
            JsonBean res = new JsonBean(500, message);
            ObjectMapper objectMapper = new ObjectMapper();
            String resStr = objectMapper.writeValueAsString(res);

            writer.print(resStr);
        } catch (IOException e) {
            log.error("拦截器输出流异常[{}]", e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}
